package com.toyota.toyotaownerspoc.takeAPicture;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import java.io.ByteArrayOutputStream;
import java.io.File;

import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.SensorManager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.widget.LinearLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.toyota.toyotaownerspoc.R;
import com.toyota.toyotaownerspoc.service.Service;
import com.toyota.toyotaownerspoc.util.ImageUtility;

import java.io.IOException;
import java.util.List;
import android.view.OrientationEventListener;
import utility.FileUtility;
import utility.ScreenUtility;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera.Size;
import android.view.SurfaceHolder;

public class TakeAPictureActivity extends Activity {

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		//getMenuInflater().inflate(R.menu.take_apicture, menu);
		return true;
	}

		// camera object that is used globally in this activity and also passed
		// reference to PreviewSurface inner class
		private Camera globalCamera;
		private int cameraId = 0;
		// bitmap that would created after picture is taken and converted from
		// camera bytes
		private Bitmap bmpOfTheImageFromCamer = null;
		// global flag whether a camera has been detected
		private boolean isThereACamera = false;
		// layout for this activity
		private RelativeLayout RelativeLayoutBarcodeScanner= null;
		// CameraPreview extends SurfaceView displays preview of images from the
		// Camera
		private CameraPreview newCameraPreview = null;
		// used to inflate the xml layout
		private SurfaceView surfaceViewBarcodeScanner = null;
		private boolean cameraPreviewing = false;
		// this continueToAutomaticallyDecode flag is initially set to TRUE, but
		// will be set to FALSE on the first successful decode OR when a crucial
		// method in the code process fails or throws an exception
		private volatile boolean continueToAutomaticallyDecode = true;
		// global flag used to indicate picture taking & decoding is in progress
		private volatile boolean takingPictureAndDecodeInprogress = false;
		// Bitmap options for bitmap creation from camera picture
		BitmapFactory.Options options = null;

		private OrientationEventListener orientationEventListener = null;
		// 1 means the screen is PORTRAIT and 2 means screen is LANDSCAPE
		private int latestScreenOrientation = 1;
		private Matrix rotationMatrix90CounterClockWise= null;
	


		
		public boolean isContinueToAutomaticallyDecode() {

			return continueToAutomaticallyDecode;
		}

		public void setContinueToAutomaticallyDecode(
				boolean continueToAutomaticallyDecode) {
			
				this.continueToAutomaticallyDecode = continueToAutomaticallyDecode;
			
		}

		public boolean isTakingPictureAndDecodeInprogress() {
			return takingPictureAndDecodeInprogress;
		}

		public void setTakingPictureAndDecodeInprogress(
				boolean takingPictureAndDecodeInprogress) {
			
				this.takingPictureAndDecodeInprogress = takingPictureAndDecodeInprogress;
			
		}

		/*
		 * This method , finds FEATURE_CAMERA, opens the camera, set parameters ,
		 * add CameraPreview to layout, set camera surface holder, start preview
		 */
		@SuppressLint("InlinedApi")
		private void initializeGlobalCamera() {

			try {
				if (!getPackageManager().hasSystemFeature(
						PackageManager.FEATURE_CAMERA)) {
					Toast.makeText(this, "No camera on this device",
							Toast.LENGTH_LONG).show();
				} else { // check for front camera ,and get the ID
					cameraId = CameraUtility.findFrontFacingCamera();
					if (cameraId < 0) {

						Toast.makeText(this, "No front facing camera found.",
								Toast.LENGTH_LONG).show();
					} else {

						Log.d("ClassScanViewBarcodeActivity",
								"camera was found , ID: " + cameraId);
						// camera was found , set global camera flag to true
						isThereACamera = true;
						// OPEN
						globalCamera = getGlobalCamera(cameraId);
						// parameters auto focus
						
						boolean FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED = CameraUtility.isFocusModeSupported(globalCamera,Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
						if (FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED)
						{
						globalCamera.getParameters().setFocusMode(
								Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
						Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() is FOCUS_MODE_CONTINUOUS_PICTURE supported? ",
								String.valueOf(FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED));
						}
						else
						{
							Toast.makeText(this, "Continous Focus Is Not Supported.",
									Toast.LENGTH_LONG).show();
							Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() is FOCUS_MODE_CONTINUOUS_PICTURE supported? ",
									String.valueOf(FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED));
						}
						
						// set picture format to JPEG
						
						globalCamera.getParameters().setPictureFormat(
								ImageFormat.JPEG);
						autoFocusSetupForBarcode(globalCamera);
						/*
						 * START early setup variables & setting used in
						 * jpegCallback in order to optimize the jpegCallback code
						 */
						options = new BitmapFactory.Options();
						// option set for down sampling he captured image taken from
						// the camera in order to MemoryOutOfBounds exception
						options.inSampleSize = 4;
						// image quality rather than speed in order to achieve early
						// barcode detection & decode
						options.inPreferQualityOverSpeed = false;
					
						boolean FLASH_MODE_SUPPORTED = CameraUtility.isFlashSupported(this,globalCamera,Camera.Parameters.FLASH_MODE_TORCH);
								if (FLASH_MODE_SUPPORTED)
								{
									Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() is FLASH_MODE_TORCH supported? ",
											String.valueOf(FLASH_MODE_SUPPORTED));
						CameraUtility.turnOnFlashlight(globalCamera,this);
								}
								else
								{
									Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() is FLASH_MODE_TORCH supported? ",
											String.valueOf(FLASH_MODE_SUPPORTED));
								}
								
						rotationMatrix90CounterClockWise = new Matrix();
						rotationMatrix90CounterClockWise.postRotate(90);

						// pass surfaceView to CameraPreview
						newCameraPreview = new CameraPreview(this, globalCamera) {

							@Override
							public boolean onTouchEvent(MotionEvent event) {
								Log.d("ClassScanViewBarcodeActivity",
										" onTouchEvent(MotionEvent event) ");

								globalCamera.autoFocus(autoFocusCallbackTakeInFocusPicture);

								return super.onTouchEvent(event);
							}

						};

						// pass CameraPreview to Layout
						RelativeLayoutBarcodeScanner.addView(newCameraPreview);
					
					
						// give reference SurfaceView to camera object
						globalCamera.setPreviewDisplay(surfaceViewBarcodeScanner
								.getHolder());

						// PREVIEW
						if (cameraPreviewing != true) {
							globalCamera.startPreview();
						}

						Log.d("ClassScanViewBarcodeActivity",
								"camera opened & previewing");
					}
				}// end else ,check for front camera
			}// end try
			catch (Exception exc) {

				// in case of exception release resources & cleanup
				if (globalCamera != null) {
					globalCamera.stopPreview();
					cameraPreviewing = false;
					globalCamera.setPreviewCallback(null);
					globalCamera.release();
					globalCamera = null;
					options = null;
					
				

				}
				Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() exception:",
						exc.getMessage());
				exc.printStackTrace();
			}// end catch

		}// end ini

		// onCreate, instantiates layouts & surfaceView used for video preview
		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_take_apicture);
			
			Log.d("ClassScanViewBarcodeActivity", "onCreate ");

			// create surfaceView for previewing of camera image
			RelativeLayoutBarcodeScanner = (RelativeLayout) findViewById(R.id.layoutForTakeAPicturePreview);
			surfaceViewBarcodeScanner = (SurfaceView) findViewById(R.id.surfaceViewTakeAPicture);
			
			initializeGlobalCamera();
		

			// instantiate orientationEventListener
			orientationEventListener = new OrientationEventListener(this,
					SensorManager.SENSOR_DELAY_NORMAL) {

				@Override
				public void onOrientationChanged(int arg0) {

		
					/*
					latestScreenOrientation = ScreenUtility
							.getScreenOrientation(RelativeLayoutBarcodeScanner.getContext());

					Log.d("ClassScanViewBarcodeActivity",
							"latestScreenOrientation: " + latestScreenOrientation);

					if (orientationEventListener.canDetectOrientation()) {
						orientationEventListener.enable();
						Log.d("ClassScanViewBarcodeActivity",
								"enabled orientationEventListener: "
										+ String.valueOf(orientationEventListener
												.canDetectOrientation()));
					} else {
						Log.d("ClassScanViewBarcodeActivity",
								"enabled orientationEventListener: "
										+ String.valueOf(orientationEventListener
												.canDetectOrientation()));
					}
	*/
				}
				
			};
			

		}// end onCreate
		
		public void onBackPressed(){
			
			if (globalCamera != null) {
				globalCamera.stopPreview();
				cameraPreviewing = false;
				globalCamera.setPreviewCallback(null);
				globalCamera.release();
				globalCamera = null;
			}
			
			 Intent i = new Intent(this.getApplicationContext(), Service.class);
			 startActivity(i);
		
			 
		}

		
		@Override
		protected void onResume() {

			Log.d("ClassScanViewBarcodeActivity, onResume() globalCamera:",
					String.valueOf(globalCamera));

			initializeGlobalCamera();
		
		
			
			/*
			if (orientationEventListener != null) {
				orientationEventListener.enable();
			}
			 */	

			super.onResume();
		}

		@Override
		protected void onStop() {

			if (globalCamera != null) {
				globalCamera.stopPreview();
				cameraPreviewing = false;
				globalCamera.setPreviewCallback(null);
				globalCamera.release();
				globalCamera = null;
			}

			/*
			if (orientationEventListener != null) {
				orientationEventListener.enable();
			}
			 */	
			super.onStop();
		}

		@Override
		protected void onPause() {
			if (globalCamera != null) {
				globalCamera.stopPreview();
				cameraPreviewing = false;
				globalCamera.setPreviewCallback(null);
				globalCamera.release();
				globalCamera = null;
				options = null;
				
				
			}
			/*
			if (orientationEventListener != null) {
				orientationEventListener.enable();
			}
			 */	
			super.onPause();
		}// end onPause()

		public void onConfigurationChanged(Configuration newConfig) {
			super.onConfigurationChanged(newConfig);

			latestScreenOrientation = ScreenUtility.getScreenOrientation(RelativeLayoutBarcodeScanner.getContext());

			Log.d("ClassScanViewBarcodeActivity", "latestScreenOrientation: "
					+ latestScreenOrientation);

		}

		// callback used by takePicture()
		
		PictureCallback jpegCallback = new PictureCallback() {

			@SuppressLint("NewApi")
			public void onPictureTaken(byte[] imgData, Camera camera) {

			Bitmap bmpOfTheImageFromCamera = null; 

				if (imgData != null && camera != null) {
					
					
					bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(imgData, 0,
							imgData.length, options);

					if (bmpOfTheImageFromCamera != null) {

						// for samsung galaxy s devices only rotate 90 degrees
						bmpOfTheImageFromCamera = Bitmap.createBitmap(
								bmpOfTheImageFromCamera, 0, 0,
								bmpOfTheImageFromCamera.getWidth(),
								bmpOfTheImageFromCamera.getHeight(),
								rotationMatrix90CounterClockWise, true);
					}

					//back to byte [] for in order to save on SD
					imgData = ImageUtility.bitmapToByteArray(bmpOfTheImageFromCamera);
		    
			CameraUtility.savePictureInSDcardPicturesDirectory( imgData,"MyVehicleBackground");
				} else {
					Log.d("ClassScanViewBarcodeActivity", "onPictureTaken()");
				}
				

					globalCamera.startPreview();
					cameraPreviewing = true;
				
			}
		};// jpegCallback implementation


		public Camera getGlobalCamera(int CameraId) {
			if (globalCamera == null) {
				// OPEN
				globalCamera = Camera.open(CameraId);
			}

			return globalCamera;

		}



		@SuppressWarnings("finally")
		public byte[] bitmapToByteArray(Bitmap bitmap) {
			ByteArrayOutputStream baoStream = null;
			try {
				baoStream = new ByteArrayOutputStream();
				bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baoStream);
			} catch (Exception exc) {
				Log.d("ClassScanViewBarcodeActivity, bitmapToByteArray (Bitmap bitmap) Exception: ",
						exc.getMessage());
				setContinueToAutomaticallyDecode(false);
			} finally {
				return baoStream.toByteArray();
			}
		}

		public void takePicture() {

			setTakingPictureAndDecodeInprogress(true);
			Log.d("ClassScanViewBarcodeActivity", "takePicture()");
			try {

				// if true take a picture
				if (isThereACamera) {
					Log.d("ClassScanViewBarcodeActivity",
							"setOnClickListener() isThereACamera: "
									+ isThereACamera);

					if (cameraPreviewing != true) {
						globalCamera.startPreview();
						cameraPreviewing = true;
					}

					globalCamera.takePicture(null, null, jpegCallback);

				}

			}// end try
			catch (Exception exc) {

				// in case of exception release resources & cleanup
				if (globalCamera != null) {
					globalCamera.stopPreview();
					globalCamera.setPreviewCallback(null);
					globalCamera.release();
					globalCamera = null;
					//
					setContinueToAutomaticallyDecode(false);
					cameraPreviewing = false;
				}
				Log.d("ClassScanViewBarcodeActivity setOnClickListener() exceprtion:",
						exc.getMessage());
				exc.printStackTrace();
			}// end catch

		}// end takePicture()

		public void autoFocusSetupForBarcode(Camera camera) {
			if (camera != null) {
				String focusArea = camera.getParameters().getFocusMode();

				if (focusArea.equalsIgnoreCase(Camera.Parameters.FOCUS_MODE_MACRO)
						|| focusArea
								.equalsIgnoreCase(Camera.Parameters.FOCUS_MODE_AUTO)) {
					camera.getParameters().setSceneMode(
							Camera.Parameters.SCENE_MODE_BARCODE);
				}
			}
		}

		// inner class SurfaceView used to preview incoming images from Camera
		
		
		/** A basic Camera preview class */
		private class CameraPreview extends SurfaceView implements
				SurfaceHolder.Callback {
			private SurfaceHolder mHolder;
			private Camera mCamera;
			private Context context;

			//
			private ImageView imageView = null;
			private Bitmap guidanceScannerFrame = null;

			public CameraPreview(Context context, Camera camera) {
				super(context);

				mCamera = camera;
				this.context = context;
				// Install a SurfaceHolder.Callback so we get notified when the
				// underlying surface is created and destroyed.
				mHolder = getHolder();
				mHolder.addCallback(this);
				// deprecated setting, but required on Android versions prior to 3.0
				mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

				setWillNotDraw(false);
				setFocusable(true);
				requestFocus();
			}

			@SuppressLint("NewApi")
			private void initializeCameraForSurfaceView() {

			try
			{
				mCamera.stopPreview();
				cameraPreviewing = false;

				Camera.Parameters p = mCamera.getParameters();

				p.set("orientation", "portrait");
				/*
				 * for samsung galaxy s only, rotate the image by 90 degrees
				 * clockwise , in order to correctly displayed the image , images
				 * seem to be -90 degrees (counter clockwise) rotated
				 */
				mCamera.setDisplayOrientation(90);

				// get width & height of the SurfaceView
				int SurfaceViewWidth = this.getWidth();
				int SurfaceViewHeight = this.getHeight();

				List<Size> sizes = p.getSupportedPreviewSizes();
				Size optimalSize = CameraUtility.getOptimalPreviewSize(sizes, SurfaceViewWidth,
						SurfaceViewHeight);

				// set parameters
				p.setPreviewSize(optimalSize.width, optimalSize.height);
				
				boolean FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED = CameraUtility.isFocusModeSupported(globalCamera,Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
				if (FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED)
				{
				globalCamera.getParameters().setFocusMode(
						Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
				Log.d("ClassScanViewBarcodeActivity, initializeCameraForSurfaceView() is FOCUS_MODE_CONTINUOUS_PICTURE supported? ",
						String.valueOf(FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED));
				}
				else
				{
					
					Log.d("ClassScanViewBarcodeActivity, initializeCameraForSurfaceView() is FOCUS_MODE_CONTINUOUS_PICTURE supported? ",
							String.valueOf(FOCUS_MODE_CONTINUOUS_PICTURE_SUPPORTED));
				}

				mCamera.setParameters(p);
			
			    mCamera.setPreviewDisplay(mHolder);
				mCamera.startPreview();
				
				cameraPreviewing = true;
			
				}
				catch (IOException exc)
				{
				exc.printStackTrace();
				}
			}//end initializeCameraForSurfaceViewOnSurfaceChanged



			@SuppressLint("InlinedApi")
			public void surfaceCreated(SurfaceHolder holder) {
				try
				{
				initializeCameraForSurfaceView();
				}
				catch (Exception exc)
				{
					exc.printStackTrace();
					Log.d("surfaceCreated(SurfaceHolder holder) exception:",  String.valueOf(exc.getMessage()));
				}

			}

			public void surfaceDestroyed(SurfaceHolder holder) {
				// empty. Take care of releasing the Camera preview in your
				// activity.
			}

			@SuppressLint("InlinedApi")
			public void surfaceChanged(SurfaceHolder holder, int format, int w,
					int h) {
				// If your preview can change or rotate, take care of those events
				// here.
				// Make sure to stop the preview before resizing or reformatting it.

				initializeCameraForSurfaceView();


			}// end surfaceChanged()

			
			AutoFocusCallback autoFocusCallbackTakeInFocusPicture = new AutoFocusCallback() {
				@Override
				public void onAutoFocus(boolean success, Camera camera) {

					if (success && isTakingPictureAndDecodeInprogress() != true)

					{
							takePicture();

							Log.d("***TakeAPictureActivity, onAutoFocus(boolean success, Camera camera)","success: " + success);
					 
				}// end onAutoFocus(boolean success, Camera camera)

			}; // end TakeAPictureActivity instantiation


	
};



		}
}

